#include "buffer.h"
CBuffer::CBuffer(size_t  initialSize) : m_buffer(initialSize),m_readerIndex(0),m_writerIndex(0)
{
    assert(readableBytes() ==0);
    assert(writeableBytes() == initialSize);
    assert(prependableBytes()==0);
}

size_t CBuffer::readableBytes() const
{
    return m_writerIndex - m_readerIndex;
}

size_t CBuffer::writeableBytes() const
{
    return m_buffer.size() - m_writerIndex;
}
size_t CBuffer::prependableBytes() const
{
    return m_readerIndex;
}
const char* CBuffer::peek() const
{
    return begin() + m_writerIndex;
}
char *CBuffer::beginWrite()
{
    return begin() + m_writerIndex;
}
const char* CBuffer::beginWrite() const
{
    return begin() + m_writerIndex;
}
void CBuffer::ensureWriteableBytes(size_t len)
{
    if(writeableBytes() < len)
    {
        makeSpace(len);
    }
    assert(writeableBytes() >= len);
}
void CBuffer::hasWritten(size_t len)
{
    m_writerIndex += len;
}
void CBuffer::unwrite(size_t len)
{
    assert(len <= readableBytes());
    m_writerIndex -= len;
}

void CBuffer::retrieve(size_t len)
{
    if(len < readableBytes())
    {
        m_readerIndex += len;
    }
    else 
    {
        retrieveAll();
    }
}
void CBuffer::retrieveUntil(const char* end)
{
    assert(peek() <= end);
    assert(end <= beginWrite());
    retrieve(end - peek());
}
void CBuffer::retrieveAll()
{
    bzero(&m_buffer[0], m_buffer.size());
    m_readerIndex = 0;
    m_writerIndex = 0;
}
std::string CBuffer::retrieveAllAsString()
{
    return retrieveAllAsString(readableBytes());
}

std::string CBuffer::retrieveAllAsString(size_t len)
{
    assert(len <= readableBytes());
    std::string res(peek(), len);
    retrieve(len);
    return res;
}
void CBuffer::append(const std::string &str)
{
    append(str.data(), str.length());
}

void CBuffer::append(const char* str, size_t len)
{
    ensureWriteableBytes(len);
    std::copy(str, str+len, beginWrite());
    hasWritten(len);
}

void CBuffer::append(const void* data, size_t len)
{
    append(static_cast<const char*> (data), len);
}
ssize_t CBuffer::readFd(int fd, int* Errno)
{
    char extrabuf[65536];
    struct iovec vec[2];
    const size_t writeable = writeableBytes();
    //分散读 m_buffer 内writeable 字节(堆区) + 固定 extrabuf (栈区)
    vec[0].iov_base = begin() + m_writerIndex;
    vec[0].iov_len = writeable;
    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof(extrabuf);
    //如果writable 已经很大了， 就无需将第二块内存分配出去
    const int iovcnt = (writeable < sizeof(extrabuf)?2 :1);
    const ssize_t len = readv(fd, vec, iovcnt);
    if(len < 0)
    {
        *Errno = errno;
    }
    else if (static_cast<size_t>(len) <= writeable)
    {
        m_writerIndex +=len;
    }
    else 
    {
        m_writerIndex = m_buffer.size();
        append(extrabuf, len - writeable);
    }
    return len;
}